package com.xayq.orap.oauth.token;

import javax.servlet.http.HttpServletResponse;

import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.xayq.orap.model.AccessToken;
import com.xayq.orap.model.ClientDetails;
import com.xayq.orap.model.OAuthCode;
import com.xayq.orap.utils.CommonUtils;

@Component
public class AuthorizationCodeTokenHandler extends AbstractOAuthTokenHandler {

    private static final Logger LOG = LoggerFactory.getLogger(AuthorizationCodeTokenHandler.class);


    /*
    *
    * /oauth/token?client_id=unity-client&client_secret=unity&grant_type=authorization_code&code=zLl170&redirect_uri=redirect_uri
    * */
    @Override
    public void handleAfterValidation() throws OAuthProblemException, OAuthSystemException {

        //response token, always new
        responseToken();
        //remove code lastly
        removeCode();
    }

    private void removeCode() {
        String code = tokenRequest.getCode();
        boolean result = oAuthService.removeOAuthCode(code, clientDetails());
        LOG.debug("Remove code: {} result: {}", code, result);
    }

    private void responseToken() throws OAuthSystemException {
    	String code = tokenRequest.getCode();
    	OAuthCode oauthCode = oAuthService.loadOAuthCode(code, clientDetails());
        AccessToken accessToken = oAuthService.retrieveNewAccessToken(clientDetails(),oauthCode);
        OAuthResponse tokenResponse = createTokenResponse(accessToken, false);

        LOG.debug("'authorization_code' response: {}", tokenResponse);
        CommonUtils.writeOAuthJsonResponse(response, tokenResponse);
    }


	@Override
	protected OAuthResponse validatePlus() throws OAuthSystemException {
		// TODO Auto-generated method stub
		//ClientDetails clientDetails = clientDetails();
		//validate redirect_uri
        String redirectURI = tokenRequest.getRedirectURI();
        if (redirectURI == null || !redirectURI.equals(clientDetails.getRedirectUri())) {
            LOG.debug("Invalid redirect_uri '{}', client_id = '{}'", redirectURI, clientDetails.getClientId());
            return invalidRedirectUriResponse();
        }

        //validate code
        String code = tokenRequest.getCode();
        OAuthCode oauthCode = oAuthService.loadOAuthCode(code, clientDetails());
        if (oauthCode == null) {
            LOG.debug("Invalid code '{}', client_id = '{}'", code, clientDetails.getClientId());
            return invalidCodeResponse(code);
        }

		return null;
	}
	
	private OAuthResponse invalidCodeResponse(String code) throws OAuthSystemException {
        return OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
                .setError(OAuthError.TokenResponse.INVALID_GRANT)
                .setErrorDescription("Invalid code '" + code + "'")
                .buildJSONMessage();
    }

}
